#ifndef _DEBUGMODE_H_
#define _DEBUGMODE_H_

#ifdef _DEBUG

#define DEBUG_LOG_FILE_NAME "clqa_debug.log"

#include <stdio.h>
#include <time.h>
#include <Windows.h>
#include <share.h>

FILE* gDebugFile;
CRITICAL_SECTION gDebugLogCriticalSection;
volatile LONG gInitialized;    // 0 - the CS needs initialization, 1 - the CS is being initialized, 2 - the CS can be aquired, 3 - the CS will get uninitialized

#define DebugLog(...)                                                                                                                                           \
{                                                                                                                                                               \
    SYSTEMTIME st;                                                                                                                                              \
    GetLocalTime(&st);                                                                                                                                          \
    if (!InterlockedCompareExchange(&gInitialized, 1, 0))                                                                                                       \
    {                                                                                                                                                           \
        DWORD lastError = GetLastError();                                                                                                                       \
        InitializeCriticalSection(&gDebugLogCriticalSection);                                                                                                   \
        gDebugFile = _fsopen(DEBUG_LOG_FILE_NAME, "a", _SH_DENYWR);                                                                                             \
        setvbuf(gDebugFile, NULL, _IONBF, 0);                                                                                                                   \
        fprintf(                                                                                                                                                \
            gDebugFile,                                                                                                                                         \
            "\n\n------------------------------------------ Log STARTED  at [%d/%02d/%02d %02d:%02d:%02d:%03d] ------------------------------------------\n\n", \
            st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);                                                                  \
        SetLastError(lastError);                                                                                                                                \
        InterlockedIncrement(&gInitialized);                                                                                                                    \
    }                                                                                                                                                           \
    while (gInitialized == 1) {Sleep(100);}                                                                                                                     \
    if (gInitialized == 2)                                                                                                                                      \
    {                                                                                                                                                           \
        EnterCriticalSection(&gDebugLogCriticalSection);                                                                                                        \
        fprintf(                                                                                                                                                \
            gDebugFile,                                                                                                                                         \
            "[%d/%02d/%02d %02d:%02d:%02d:%03d] % 18s, % 4d: ",                                                                                                 \
            st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,                                                                   \
            strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1) : __FILE__, __LINE__);                                                                      \
        fprintf(gDebugFile, __VA_ARGS__);                                                                                                                       \
        fprintf(gDebugFile, "\n");                                                                                                                              \
        LeaveCriticalSection(&gDebugLogCriticalSection);                                                                                                        \
    }                                                                                                                                                           \
}

// This should be called when everything is done, TODO: COMPLETE TSness
#define EnsureToCloseDebugeLogFile()                                                                                                                            \
{                                                                                                                                                               \
    while (gInitialized == 1) {Sleep(100);}                                                                                                                     \
    if (InterlockedCompareExchange(&gInitialized, 3, 2) == 2)                                                                                                   \
    {                                                                                                                                                           \
        SYSTEMTIME st;                                                                                                                                          \
        GetLocalTime(&st);                                                                                                                                      \
        fprintf(                                                                                                                                                \
            gDebugFile,                                                                                                                                         \
            "\n------------------------------------------ Log FINISHED at [%d/%02d/%02d %02d:%02d:%02d:%03d] ------------------------------------------\n\n\n", \
            st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);                                                                  \
        fclose(gDebugFile);                                                                                                                                     \
        gInitialized = 0;                                                                                                                                       \
        gDebugFile = NULL;                                                                                                                                      \
        DeleteCriticalSection(&gDebugLogCriticalSection);                                                                                                       \
    }                                                                                                                                                           \
}
#else

#define DebugLog(...);

#define EnsureToCloseDebugeLogFile();

#endif 

#endif //_DEBUGMODE_H_